﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Proggy.Web.Cms.AppHelpers;
using Proggy.Web.Cms.Core.Configuration;
using System.Web.Mvc;
using Proggy.Web.Cms.Core.ViewModels;
using Proggy.Web.Cms.Core.ModelBinding;
using System.Configuration;
using Proggy.Web.Cms.Core.Seo.Service.Concrete;
using System.Threading;
using Proggy.Web.Cms.Cache;
using Proggy.Web.Cms.Context;
using Proggy.Web.Cms.Core.Seo.Service.Abstract;
using Ninject;
using System.Web;
using System.IO;
using Proggy.Web.Cms.Repositories.Published;
using Proggy.Web.Cms.Core.ContentModels;

namespace Proggy.Web.Cms.Core
{
    /// <summary>
    /// Manager object for Proggy.Web.Cms.Core
    /// </summary>
    public class ProggyCoreManager
    {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="app"></param>
        private ProggyCoreManager() { }


        /// <summary>
        /// Singleton instance
        /// </summary>
        public static ProggyCoreManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new ProggyCoreManager();
                }
                return _instance;
            }
        }
        private static ProggyCoreManager _instance;

        /// <summary>
        /// Application start
        /// </summary>
        /// <param name="app"></param>
        public void ProggyCoreApplicationStart(ProggyHttpApplication app)
        {
            startAll(app);
        }

        /// <summary>
        /// Start all services...
        /// </summary>
        private void startAll(ProggyHttpApplication app)
        {
            // dand
            setDragAndDrop();

            // start thread
            new Thread(() =>
            {
                // sitemap
                checkForSiteMap();

                // robots
                SetRobotsFile();

            }).Start();
        }

        /// <summary>
        /// Set robots file
        /// </summary>
        public void SetRobotsFile()
        {
            // get service
            var service = DependencyResolver.Current.GetService<IRobotsFileService>();

            // set robots
            service.GenerateRobotsFile();
        }

        /// <summary>
        /// Checks for site map
        /// </summary>
        private void checkForSiteMap()
        {
            // get service
            var service = DependencyResolver.Current.GetService<ISeoSiteMapService>();

            // check file
            if (!File.Exists(service.RootFolderPath + "sitemap.xml"))
            {
                this.UpdateSiteMap(service);
            }
        }

        /// <summary>
        /// set drag and drop stuff
        /// </summary>
        private void setDragAndDrop()
        {
            var dragAndDropFac = new DragAndDropManager();
            dragAndDropFac.SetCache();
            ModelBinders.Binders.Add(typeof(ConfigureDragAndDropPartViewModel), new ConfigureDragAndDropPartViewModelBinder());
        }

        /// <summary>
        /// Update site map
        /// </summary>
        public void UpdateSiteMap()
        {
            // get service
            var service = DependencyResolver.Current.GetService<ISeoSiteMapService>();

            //
            updateSiteMap(service);
        }

        /// <summary>
        /// Update site map
        /// </summary>
        public void UpdateSiteMap(ISeoSiteMapService service)
        {
            updateSiteMap(service);
        }

        /// <summary>
        /// Update site map
        /// </summary>
        /// <param name="service"></param>
        private void updateSiteMap(ISeoSiteMapService service)
        {
            // get repo
            var repo = CachedContentManager.GetRepositoryInstance(false);

            // error string
            var error = "";

            // update site map
            if (!service.UpdateXmlSiteMap(repo, ref error))
            {
                throw new Exception("Error updating sitemap: " + error);
            }
        }

        /// <summary>
        /// Set kernel
        /// </summary>
        /// <param name="kernel"></param>
        public void SetKernel(IKernel kernel)
        {
            #region bind sitemap  / robots services

            // get data
            string rootUrl = FrontEndRequestContext.GetRootUrl();
            string frontPartOfUrl = ConfigurationManager.AppSettings["FrontPartOfUrl"];
            string rootFolderPath = AppDomain.CurrentDomain.BaseDirectory;// ConfigurationManager.AppSettings["RootFolderPath"];
            

            // bind site map service
            kernel
                .Bind<ISeoSiteMapService>()
                .To<SeoSiteMapService>()
                .InSingletonScope()
                .WithConstructorArgument("rootUrl", rootUrl)
                .WithConstructorArgument("frontPartOfUrl", frontPartOfUrl)
                .WithConstructorArgument("rootFolderPath", rootFolderPath);

            // bind robots service
            kernel
                .Bind<IRobotsFileService>()
                .ToMethod(m => {
                    return ProggyCoreManager.Instance.GetIRobotsFileInstance();
                });

            #endregion

        }

        public IRobotsFileService GetIRobotsFileInstance()
        {
            // get constructors
            string rootUrl = FrontEndRequestContext.GetRootUrl();
            string rootFolderPath = AppDomain.CurrentDomain.BaseDirectory;// ConfigurationManager.AppSettings["RootFolderPath"];
            var additionalDisallows = this.getRobotDisallows();
            bool autoGenerateFile = true;
            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["AutoGenerateRobotsFile"]))
            {
                autoGenerateFile = Convert.ToBoolean(ConfigurationManager.AppSettings["AutoGenerateRobotsFile"]);
            }

            // return
            return new RobotsFileService(rootFolderPath, rootUrl, additionalDisallows, autoGenerateFile);
        }

        /// <summary>
        /// Get robot disallows
        /// </summary>
        /// <returns></returns>
        private string[] getRobotDisallows()
        {
            // get repo
            var repo = DependencyResolver.Current.GetService<IPublishedContentRepository>();

            // get data
            var data = repo.GetTypedPublishedContent<ProggyCoreAddressableContentModelBase>(true)
                .Where(x => x.DisallowRobots != null && x.DisallowRobots.SavedValue)
                .ToList();

            // get output
            var output =
                data.Select(x => x.Url).ToArray();

            //
            return output;
            
        }
    }
}
